#include <assert.h>
#include <ctype.h>
#include <err.h>
#include <linux/types.h>
#include <linux/virtio_ring.h>
#include <stdbool.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>

#include "Devices.h"

void *_convert(struct iovec *iov, size_t size, size_t align, const char *name)
{
	if (iov->iov_len != size)
		errx(1, "Tamaño del elemento iovec incorrecto %zu para %s", iov->iov_len, name);
	if ((unsigned long)iov->iov_base % align != 0)
		errx(1, "Bad alignment %p for %s", iov->iov_base, name);
	return iov->iov_base;
};

/* Determina si un elemeno iovec esta o no vacio */
bool iov_empty(const struct iovec iov[], unsigned int num_iov)
{
	unsigned int i;

	for (i = 0; i < num_iov; i++)
		if (iov[i].iov_len)
			return false;
	return true;
};

/* Consume una longitud len de bytes del dispositivo. */
void iov_consume(struct iovec iov[], unsigned num_iov, unsigned len)
{
	unsigned int i;

	for (i = 0; i < num_iov; i++) {
		unsigned int used;

		used = iov[i].iov_len < len ? iov[i].iov_len : len;
		iov[i].iov_base += used;
		iov[i].iov_len -= used;
		len -= used;
	}
	assert(len == 0);
};

/* Obtiene la mascara de las caracterísitcas d elos dispositivos */
u8 *get_feature_bits(struct device *dev)
{
	return (u8 *)(dev->desc + 1) + dev->num_vq * sizeof(struct vqconfig);
};
